Mac 应用开发者的困境:使用 Electron 还是原生技术?
这篇文章讨论了 Electron 等跨平台开发框架在 Mac 应用程序中的广泛使用及其问题。作者强调,这些框架虽然简化了跨平台开发,但导致应用程序体积膨胀、性能下降。文章以 BBEdit 和 WhatsApp 为例,展示了原生应用与基于 Electron 的应用在大小、性能等方面的差异。
原文链接:https://hyperdiskapp.com/blog/too-many-mac-apps-are-being-built-with-electron/
未经允许,禁止转载!
Electron /ɪˈlɛktrɒn/ n. 1. 一种开发框架,主要使用 JavaScript、CSS 等网页技术构建跨平台的桌面应用程序。
跨平台开发的演变历程
多年来,开发者一直努力简化跨平台开发流程。早在 90 年代,史蒂夫·乔布斯的 NeXT 公司把 NeXTStep 平台发展成了 OpenStep。OpenStep 是一个颇具前瞻性的平台,但最终并未得到大规模推广。在该平台上开发者可以用 Objective-C 这种优美的编程语言来开发 Windows 应用程序。(有趣的事实:约翰·卡马克正是使用 NeXT 计算机编写了原版 DOOM 游戏。)
近年来,微软推出了一个与 OpenStep 非常相似的平台:Xamarin。该平台的目标是扩展 Windows 开发者的跨平台部署能力。
如今,经过数十年的发展,跨平台开发已逐渐成为主流。这主要得益于 React Native 和 Electron 等受网页技术的发展。然而,这种变化并不一定能带来用户体验上的提升。
NeXT 的 OpenStep 平台是跨平台开发的先锋。苹果公司收购 NeXT 后,该平台成为了 Mac 编程的基石。
外部框架的臃肿问题
应用程序使用的外部框架越多,其原生感就越弱。例如,Electron 或 React Native 这类全面的应用开发框架基本上是用自己的元素取代了传统的原生应用程序构建工具。通过这些框架构建的应用程序虽然能实现单一代码库跨多个平台运行,但这些应用既不是纯粹的 Windows 应用,也不是典型的 Mac 应用。它们更像是网页应用,即所谓的 Electron 应用。我们都清楚,基于浏览器的网页应用往往存在响应延迟、界面不一致等问题,例如复制粘贴或拖放等功能可能无法正常工作,用户还可能不确定自己的工作是否被保存,也不确定文件保存的位置等。
尽管 Electron 应用在一定程度上改善了浏览器应用的体验,比如它可以在特定平台的运行时环境中执行网页代码,实现了更紧密的操作系统功能集成(如窗口、按钮、复制粘贴等),和原生应用程序一样,还支持用户将其图标放置在 Mac 的 Dock 上。但从根本上讲,这些应用与基于浏览器的应用相比几乎没有本质区别,用户可以明显感受得到。
如何找出臃肿的应用程序
如果你想快速了解自己的 Mac 上哪些应用程序运行效率高,哪些低下,可以检查应用程序的体积。操作很简单:在 Finder 中选中应用程序,然后使用 Command-I(获取信息)指令。通常,体积小于 20MB 的应用程序被认为设计精良,而超过 100MB 的应用程序则需提供合理解释以说明其庞大体积。特别是那些超过 500MB 的应用程序,除非它们是游戏或像 Photoshop、Final Cut Pro 这样的大型专业软件,否则就有运行效率低下的嫌疑。
探索应用程序使用的框架
一个有意思的事情是,MacOS 系统中所有应用程序实际上都是文件夹。你可以打开它们来查看内部构成,这有点类似于打开汽车的引擎盖进行检查。
在 Finder 中选中一个应用程序,然后右键点击(或按下 Control 键并点击)选择“显示包内容”。这时你可以看到应用程序的内部结构。进入 Contents 文件夹,你会看到应用程序包的顶层目录,其中包含 MacOS 和 Resources 等文件夹。如果存在名为 Frameworks 的文件夹,说明该应用程序使用了外部框架。打开 Frameworks 文件夹,你可以看到应用程序所依赖的框架。例如,如果发现 Electron 框架,那么该应用就是一个基于 Electron 的应用。
框架本身同样是文件夹。你可以打开这些框架,并使用 command-I 命令来查看它们的大小。有些框架体积很小,仅用于执行一些基本任务(例如 Sparkle,它常被 Mac 开发者用来更新应用程序)。而有些框架体积庞大,甚至包含了完整的应用程序运行环境。
以 Electron 框架为例,其体积大约为 200 MB,这几乎是 Graphic.app(一款功能全面的绘图应用程序)体积的 7 倍之多,这显得非常不寻常。
“获取信息”功能可快速揭示应用程序的体积,帮助判断其效率。
两个应用程序的对比:BBEdit 和 WhatsApp
在我的 Mac 上,通常会运行几个应用程序,如 Safari、Xcode、iTerm、Mail、WhatsApp 和 BBEdit。我们选取 BBEdit 和 WhatsApp 这两个应用程序进行比较。BBEdit 是一款高效的 Mac 文本和代码编辑器,而 WhatsApp 则是效率不佳的 Electron 应用的典型代表。
在深入了解这些应用程序之前,让我们先看看它们的主要功能。BBEdit 支持大约 50 种编程语言的语法高亮,提供完整的正则表达式搜索和替换功能,具备 SFTP/FTP 浏览器、HTML 模板、代码折叠、缩略图等丰富功能。相比之下,WhatsApp 只是一个通讯应用,允许用户发送文本、图片和音频消息。
从功能上来看,你可能会认为 BBEdit 的体积应该比另一个大,但实际情况恰恰相反。BBEdit 的体积仅为 65 MB,相当合理。而 WhatsApp 的体积则高达 324 MB。
是的,你没看错,这确实是占用 324MB 磁盘空间的即时通讯应用。它几乎是苹果 Messages 应用程序体积的 100 倍,而 Messages 的功能与 WhatsApp 基本相同。这种现象显然不太合理。
应用程序的臃肿不仅仅占用空间
应用程序存储在硬盘上,无论是否运行,都会占据一定的存储空间。运行时,它们还会消耗 RAM 和 CPU 处理资源。这些因素可能导致你的 Mac 运行过热。这种不必要的资源消耗会影响整体系统性能,浪费能源,并缩短电池使用寿命。
测试 1:启动速度
这项测试涉及到使用应用程序时的“体感”,即打开应用程序时的流畅程度。高效编写的应用程序运行流畅无阻碍,不会有任何因编程不佳引起的卡顿或拖慢。
臃肿或编程不良的应用通常启动较慢。在这次测试中,BBEdit 仅需 1 秒即可启动。相比之下,WhatsApp 在 2021 年版 MacBook Pro 上的启动时间则长达 16 秒,两者之间差距显著。
测试 2:内存占用
将“内存”和“磁盘空间”混淆是一个常见误解,但它们是完全不同的概念。内存指的是 RAM——它关乎你可以同时运行多少程序。而磁盘空间则是指你可以在电脑上存储多少数据。
在常规工作场景中,BBEdit 的内存占用为 173 MB。虽然这不算少,但相较于现今大多数 Mac 机型装配的 8-32 GB 内存而言,这仅占很小一部分。
WhatsApp 的内存占用仅为 110 MB。等一下,这似乎比 BBEdit 还少……这打破了我的原有想法……哦,等等,还有其他情况。WhatsApp 实际上运行着 5 个独立的“辅助进程”,总共占用约 1.4 GB 的内存。这实际上比我预期的情况还要糟糕。
退一步来看,仅仅用来展示短信的一个即时通讯应用,竟然消耗了与 Photoshop 相当的内存资源。这就是基于 Electron 的应用的通病,我们必须遏制这种趋势。
顺便提及,这些辅助进程的名称包括 WhatsApp Helper、WhatsApp Helper (GPU)、WhatsApp Helper (Renderer) 等。一个 Mac 应用不应该需要这么多辅助进程。它们可能通过套接字、端口或共享文件进行相互通信。这并不是构建 Mac 应用的理想方式,也不应成为常态。正如《星际迷航 III》中斯科蒂所说:“管道越复杂,堵塞的可能性就越大。”
这是 BBEdit 和 WhatsApp for Mac 的启动时间对比。从点击图标到应用程序完全可用所需的时间。
测试 3:CPU 使用情况
CPU 是计算机的“大脑”。如果一个应用程序对 CPU 的使用更为节约,那么它就是一个合格的系统“公民”。这意味着更多的 CPU 资源可以分配给其他进程,降低电源消耗,并且(特别是在笔记本电脑或智能手机上)有助于延长电池寿命。
按照一般规则,当应用程序处于空闲状态时,它们应该只消耗极少量或根本不占用 CPU 资源。这是事件驱动编程的核心理念,也是几十年来公认的良好编程习惯。在空闲时仍然占用 CPU 的应用程序可能在进行某种轮询操作,即它们反复检查某些事情,而不是等待相关事件发生时才被动作用。游戏可能会这样做,但生产力软件则不应如此。
我首先测试了 BBEdit。当它处于后台并且没有执行任何操作时,其 CPU 使用率在 0.0% 到 0.1% 之间变动。这似乎是运行中的 Mac 应用程序能达到的最低值之一。
然后我转向 WhatsApp。它的主应用程序和两个辅助进程在后台时,通常会占用大约 10-15% 的 CPU。为了进一步探究是什么导致了如此高的 CPU 使用率,我在终端运行了 sample <pid> 命令来查看 WhatsApp 正在做什么。我注意到 Electron 框架内有大量活动,其中一些函数名字如:v8::internal::SetupIsolateDelegate::SetupHeap(v8::internal::Heap*)。遗憾的是,这并没有具体说明 Electron 正在做什么具体操作。
对比 BBEdit 和 WhatsApp 在活动监视器中的 CPU 使用情况。
测试 4:GPU 使用情况
在我注意到活动监视器中显示出无明显原因的重度 GPU 使用后,我开始测试 GPU 的使用情况。意外的是,WhatsApp 在后台竟然占用了大量的 GPU 资源。公平地说,这可能并非完全是 Electron 的问题。这种高占用来自名为 WhatsApp Helper (GPU) 的进程,看起来像是 Electron 的特性,但我也测试了另一款 Electron 应用(Cursor),发现其 GPU 辅助进程并未如此大量使用 GPU。因此,这个问题可能是由 WhatsApp 自身的糟糕代码造成的,而不仅仅是 Electron……或者可能是两者的结合。
另一方面,当 BBEdit 处于后台时,其 GPU 使用率为 0%,这是符合预期的正常表现。
在活动监视器中,我们可以看到退出 WhatsApp 前后 GPU 使用率的变化。
重归精简和高效的 Mac 应用程序
苹果在打造一套完整、高效的开发环境上投入了巨大努力。最佳的 Mac 应用程序是那些利用苹果自家的工具和工具包构建,并且紧密遵循其设计准则的应用……如 BBEdit️⌨️、Transmit🚚、iTerm🤓、Gifski🎬、Pixelmator🎨、HyperDisk️❤️。与此相反,像 WhatsApp🏢、Zoom🏢、Slack🏢、Discord🏢 这类应用程序倾向于整合大量庞大且低效的框架。(出于某种原因,这些应用似乎偏爱重型框架。)
当然,有时候也必不可少得需要使用到框架。如果你在开发一个大型的高端 3D 游戏,那么选择像 Unreal Engine 这样的重型框架就非常合适。在开发 Mac 应用时,你也可以通过连接一两个轻量级的单一用途框架(如 Sparkle)来保持应用的清晰和高效(最理想的情况还是不用这些框架)。
Electron 框架的使用趋势似乎正在逐渐增强。凭借我多年的经验,我见证了不少不良趋势的兴衰,我希望这个趋势最终只是一个昙花一现,而不是新的常态。
在 Mac 应用开发中,你是否也注意到了 Electron 等框架的广泛使用?它们是否真得想文中说的带来了体积膨胀和性能问题?欢迎分享你的经验和看法。
▶字节CEO梁汝波:年度目标是“加强危机感”;马斯克550亿美元薪酬方案被推翻;小米回应SU7上险价36万元 | 极客头条
▶调查 1.53 亿行代码后,发现 AI 让全球的代码质量变差了!